package com.dlc.longweisheng.chongdianxian.pub;

import android.content.Context;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.os.Handler;
import android.os.Message;

import com.dlc.longweisheng.chongdianxian.pub.mInterface.SendCallback;
import com.hoho.android.usbserial.driver.UsbSerialDriver;
import com.hoho.android.usbserial.driver.UsbSerialPort;
import com.hoho.android.usbserial.driver.UsbSerialProber;
import com.hoho.android.usbserial.util.ByteUtil;
import com.hoho.android.usbserial.util.HexDump;
import com.hoho.android.usbserial.util.LogPlus;
import com.hoho.android.usbserial.util.SerialInputOutputManager;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TemperatureUsbControl {

    private static final String TAG = TemperatureUsbControl.class.getSimpleName();
    private static final String TEMPERATURE_USB_VENDOR_ID = "067B";     //供应商id
    private static final String TEMPERATURE_USB_PRODUCT_ID = "2303";    //产品id
    private Context mContext;
    private UsbManager mUsbManager; //USB管理器
    private UsbSerialPort sTemperatureUsbPort = null;  //接体温枪的usb端口
    private SerialInputOutputManager mSerialIoManager;  //输入输出管理器（本质是一个Runnable）
    private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();  //用于不断从端口读取数据
    private int receiveCount;
    private byte[] result;
    private boolean isConnect;
    private boolean isRecing;
    private boolean isInit;

    //数据输入输出监听器
    private final SerialInputOutputManager.Listener mListener = new SerialInputOutputManager.Listener() {
        @Override
        public void onRunError(Exception e) {
            LogPlus.d(TAG, "Runner stopped.");
        }

        @Override
        public void onNewData(final byte[] data) {
            LogPlus.d(TAG, "onNewData:" + Arrays.toString(data));
            if (!isRecing) {
                isRecing = true;
                result = new byte[0];
            }
            result = byteMerger(result, data);
            receiveCount = 0;
        }
    };


    public TemperatureUsbControl(Context context) {
        mContext = context;
        startTimerTask();
    }

    public void initUsbControl() {
        if (isInit) {
            return;
        }
        LogPlus.e(TAG, "initUsbControl");
        mUsbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
        //全部设备
        List<UsbSerialDriver> usbSerialDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(mUsbManager);
        //全部端口
        List<UsbSerialPort> usbSerialPorts = new ArrayList<>();
        for (UsbSerialDriver driver : usbSerialDrivers) {
            List<UsbSerialPort> ports = driver.getPorts();
            LogPlus.d(TAG, String.format("+ %s: %s port%s", driver, Integer.valueOf(ports.size()), ports.size() == 1 ? "" : "s"));
            usbSerialPorts.addAll(ports);
        }
        String vendorId;
        String productId;
        //校验设备，设备是 2303设备
        for (UsbSerialPort port : usbSerialPorts) {
            UsbSerialDriver driver = port.getDriver();
            UsbDevice device = driver.getDevice();
            vendorId = HexDump.toHexString((short) device.getVendorId());
            productId = HexDump.toHexString((short) device.getProductId());
            LogPlus.e(TAG, "vendorId: " + vendorId);
            LogPlus.e(TAG, "productId: " + productId);
            if (vendorId.equals(TEMPERATURE_USB_VENDOR_ID) && productId.equals(TEMPERATURE_USB_PRODUCT_ID)) {
                sTemperatureUsbPort = port;
            }
        }
        if (sTemperatureUsbPort != null) {
            //成功获取端口，打开连接
            UsbDeviceConnection connection = mUsbManager.openDevice(sTemperatureUsbPort.getDriver().getDevice());
            if (connection == null) {
                LogPlus.e(TAG, "Opening device failed");
                isConnect = false;
                return;
            }
            try {
                sTemperatureUsbPort.open(connection);
                LogPlus.e(TAG, "open success");
                isConnect = true;
                isInit = true;
                //设置波特率
                sTemperatureUsbPort.setParameters(9600, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);

            } catch (IOException e) {
                //打开端口失败，关闭！
                LogPlus.e(TAG, "Error setting up device: " + e.getMessage(), e);
                try {
                    sTemperatureUsbPort.close();
                } catch (IOException e2) {
                    // Ignore.
                }
                sTemperatureUsbPort = null;
                isConnect = false;
                return;
            }
        } else {
            //提示未检测到设备
            isConnect = false;
        }
    }


    public void onDeviceStateChange() {
        //重新开启USB管理器
        stopIoManager();
        startIoManager();
    }

    public void startIoManager() {
        if (sTemperatureUsbPort != null && mSerialIoManager == null) {
            LogPlus.i(TAG, "Starting io manager ..");
            mSerialIoManager = new SerialInputOutputManager(sTemperatureUsbPort, mListener);
            mExecutor.submit(mSerialIoManager);  //实质是用一个线程不断读取USB端口
        }
    }

    public void stopIoManager() {
        if (mSerialIoManager != null) {
            LogPlus.i(TAG, "Stopping io manager ..");
            mSerialIoManager.stop();
            mSerialIoManager = null;
        }
    }

    public boolean isConnect() {
        return isConnect;
    }

    public void onPause() {
        stopIoManager();
        if (sTemperatureUsbPort != null) {
            try {
                sTemperatureUsbPort.close();
            } catch (IOException e) {
                // Ignore.
            }
            sTemperatureUsbPort = null;
        }
    }

    public void writeAsync(final byte[] data) {
        LogPlus.d("###writeAsync data: " + ByteUtil.bytes2HexStr(data));
        mSerialIoManager.writeAsync(data);
    }

    public void setSendCallback(SendCallback sendCallback) {
        this.sendCallback = sendCallback;
    }

    private SendCallback sendCallback;

    private Timer timer;

    private void startTimerTask() {
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
        timer = new Timer();
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                if (isRecing) {
                    receiveCount++;
                    if (receiveCount > 100) {
                        isRecing = false;
                        handler.sendEmptyMessage(SendCallback.SEND_CODE);
//                        LogPlus.d(TAG, "result:" + Arrays.toString(result));
//                        LogPlus.d(TAG, "result.length:" + result.length);
                    }
                }
            }
        };
        timer.schedule(timerTask, 0, 5);
    }


    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case SendCallback.SEND_CODE:
                    if (sendCallback != null) {
                        sendCallback.onResult(result);
                    }
                    break;
            }
        }
    };

    private byte[] byteMerger(byte[] bt1, byte[] bt2) {
        byte[] bt3 = new byte[bt1.length + bt2.length];
        System.arraycopy(bt1, 0, bt3, 0, bt1.length);
        System.arraycopy(bt2, 0, bt3, bt1.length, bt2.length);
        return bt3;
    }
}
